package org.ruoyi.aibox.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.ruoyi.aibox.domain.DocAuditItem;
import org.ruoyi.aibox.domain.DocAuditResult;
import org.ruoyi.aibox.domain.DocAuditResultDetail;
import org.ruoyi.aibox.mapper.DocAuditItemMapper;
import org.ruoyi.aibox.mapper.DocAuditResultDetailMapper;
import org.ruoyi.common.chat.entity.chat.*;
import org.ruoyi.common.core.exception.ServiceException;
import org.ruoyi.common.core.utils.DateUtils;
import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.common.satoken.utils.LoginHelper;
import org.ruoyi.domain.ChatModel;
import org.ruoyi.mapper.ChatModelMapper;
import org.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.ruoyi.common.chat.openai.OpenAiClient;
import org.ruoyi.common.chat.entity.chat.ChatCompletionResponse;
import org.ruoyi.common.chat.openai.CcbAiClient;
import java.util.*;

/**
 * AI模型服务
 * 负责调用AI模型进行文档审核
 */
@Slf4j
@Service
public class AiModelService {

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private DocAuditResultDetailMapper detailMapper;

    @Autowired
    private DocAuditItemMapper auditItemMapper;

    @Autowired
    private ChatModelMapper chatModelMapper;

    /**
     * 调用AI模型进行文档审核
     *
     * @param result 审核结果对象
     * @param details 审核项详情列表
     * @param chapterMap 文档章节内容映射
     * @return 更新后的审核结果
     */
    @Transactional(rollbackFor = Exception.class)
    public DocAuditResult auditDocument(DocAuditResult result, List<DocAuditResultDetail> details, Map<String, String> chapterMap) {
        try {
            // 1. 获取模型配置
            ChatModel model = getModelConfig(result.getModelName());
            // 2. 获取相关审核项配置
            List<DocAuditItem> auditItems = getAuditItems(details);
            // 3. 创建审核项ID到配置的映射
            Map<Long, DocAuditItem> itemMap = new HashMap<>();
            for (DocAuditItem item : auditItems) {
                itemMap.put(item.getId(), item);
            }
            // 4. 处理每个审核项详情，单独调用大模型
            for (DocAuditResultDetail detail : details) {
                try {
                    DocAuditItem item = itemMap.get(detail.getAuditItemId());
                    if (item != null) {
                        // 设置审核项名称和内容（如果为空）
                        if (StringUtils.isEmpty(detail.getItemName())) {
                            detail.setItemName(item.getAudititemName());
                        }
                        if (StringUtils.isEmpty(detail.getItemContent())) {
                            detail.setItemContent(item.getAudititemContent());
                        }
                        // 获取章节内容
                        String chapterContent = null;
                        if (StringUtils.isNotEmpty(item.getAuditChapter())) {
                            chapterContent = chapterMap.get(item.getAuditChapter());
                        }
                        if (chapterContent == null) {
                            chapterContent = chapterMap.get("全文");
                        }
                        // 构建prompt
                        String prompt = "";
                        if (StringUtils.isNotEmpty(item.getAudititemPrompt())) {
                            String processedContent = chapterContent;
                            int maxLength = 16000;
                            if (StringUtils.isNotEmpty(processedContent) && processedContent.length() > maxLength) {
                                processedContent = processedContent.substring(0, maxLength) + "...\n\n[内容已截断]";
                            }
                            prompt = item.getAudititemPrompt().replace("{chapter}", processedContent);
                        }
                        // 构建ChatCompletion
                        String sysPrompt = model.getSystemPrompt();
                        if (StringUtils.isEmpty(sysPrompt)) {
                            sysPrompt = "你是一名软件技术方案与详细设计审核专家";
                        }
                        Message systemMessage = Message.builder().role("system").content(sysPrompt).build();
                        Message userMessage = Message.builder().role("user").content(prompt + "\n审核内容如下：" + chapterContent).build();
                        ChatCompletion chatCompletion = ChatCompletion.builder()
                            .model(model.getModelName())
                            .messages(Arrays.asList(systemMessage, userMessage))
                            .temperature(0.7)
                            .stream(false)
                            .build();
                       detail.getAuditItemResult();
                        // 新增日志，记录请求和返回
                        log.info("[AI审核] detailId={}, model={}, prompt={}", detail.getDetailId(), model.getModelName(),prompt);

                        String content = "";
                        if (model.getModelDescribe() != null && model.getModelDescribe().startsWith("CCB")) {
                            // CCB专用调用
                            CcbAiClient ccbClient = new CcbAiClient();
                            CcbAiClient.CcbResult ccbResult = ccbClient.chatCompletionCcb(model.getApiHost(), model.getApiKey(), model.getModelName(), Arrays.asList(systemMessage, userMessage));
                            // 1. codeid
                            detail.setAuditStatus(ccbResult.getCodeid());
                            // 2. content
                            content = ccbResult.getContent() != null ? ccbResult.getContent() : "无内容返回";
                            detail.setAuditAdvice(content);
                            // 3. reasoning_content
                            if (ccbResult.getReasoningContent() != null) {
                                detail.setAuditSuggestion(ccbResult.getReasoningContent());
                            } else {
                                detail.setAuditSuggestion("无思考过程");
                            }
                            // 4. content前20字符关键词判断
                            String prefix = content.length() > 20 ? content.substring(0, 20) : content;
                            if (prefix.contains("不通过")) {
                                detail.setAuditItemResult("fail");
                            } else if (prefix.contains("不涉及")) {
                                detail.setAuditItemResult("notApplicable");
                            } else if (prefix.contains("异常")) {
                                detail.setAuditItemResult("exception");
                            } else if (prefix.contains("通过")) {
                                detail.setAuditItemResult("pass");
                            }
                        } else {
                            // 原有OpenAiClient调用
                            OpenAiClient client = OpenAiClient.builder()
                                .apiKey(Collections.singletonList(model.getApiKey()))
                                .apiHost(model.getApiHost())
                                .build();
                            ChatCompletionResponse response = client.chatCompletion(chatCompletion);
                            if (response != null && response.getChoices() != null && !response.getChoices().isEmpty()) {
                                content = response.getChoices().get(0).getMessage().getContent().toString();
                            }
                        }
                        boolean hasThinking = content.contains("> Thinking");
                        String auditAdvice = hasThinking?content.split("> Thinking")[1]:content;
                        String auditSuggestion = hasThinking?content.split("> Thinking")[0]:content;
                        // 4. content前30字符关键词判断
                        String prefix = auditAdvice.substring(0, 30);
                        if (prefix.contains("不通过")) {
                            detail.setAuditItemResult("fail");
                        } else if (prefix.contains("不涉及")) {
                            detail.setAuditItemResult("notApplicable");
                        } else if (prefix.contains("异常")) {
                            detail.setAuditItemResult("exception");
                        } else if (prefix.contains("通过")) {
                            detail.setAuditItemResult("pass");
                        }
                        detail.setAuditAdvice(auditAdvice);
                        detail.setAuditSuggestion(auditSuggestion);
                        detail.setUpdateBy(LoginHelper.getUserId());
                        detail.setUpdateTime(DateUtils.getNowDate());
                    }
                    // 新增日志，记录请求和返回
                    log.info("[AI审核] detailId={}, model={},  返回内容={}", detail.getDetailId(), model.getModelName(), detail.getAuditAdvice());

                } catch (Exception e) {
                    log.error("明细AI审核异常: detailId={}", detail.getDetailId(), e);
                    detail.setAuditStatus("3"); // 处理异常
                    detail.setAuditSuggestion("明细处理异常: " + e.getMessage());
                }
            }
            // 5. 批量更新详情
            if (!details.isEmpty()) {
                detailMapper.updateBatchDocAuditResultDetail(details);
            }
            // 6. 统计审核结果并赋值到result
            int passCount = 0, failCount = 0, notInvolveCount = 0, exceptionCount = 0;
            for (DocAuditResultDetail detail : details) {
                String itemResult = detail.getAuditItemResult();
                if ("pass".equals(itemResult)) passCount++;
                else if ("fail".equals(itemResult)) failCount++;
                else if ("notApplicable".equals(itemResult)) notInvolveCount++;
                else if ("exception".equals(itemResult)) exceptionCount++;
            }
            int total = details.size();
            int score = total > 0 ? (int)Math.round(passCount * 100.0 / total) : 0;
            result.setAuditPassItems((long)passCount);
            result.setTotalItems((long)total);
            result.setAuditScore((long)score);
            // 结论
            String conclusion = String.format("共%d项，通过%d项，不涉及%d项，不通过%d项，评分%d分，整体结论：%s", total, passCount, notInvolveCount, failCount, score, score >= 60 ? "通过" : "不通过");
            result.setAuditAiConclusion(conclusion);
            result.setAuditStatus(score >= 60 ? "1" : "0");
            // 审核耗时
            long endTime = System.currentTimeMillis();
            if (result.getCreateTime() != null) {
                long cost = endTime - result.getCreateTime().getTime();
                result.setAuditTime(cost / 1000); // 秒
            } else {
                result.setAuditTime(0L);
            }
            // 7. 返回主结果
            return result;
        } catch (Exception e) {
            log.error("AI模型调用异常: taskId={}, resultId={}", result.getTaskId(), result.getResultId(), e);
            throw new ServiceException("AI模型调用失败: " + e.getMessage(), 500);
        }
    }
    
    /**
     * 获取模型配置
     */
    private ChatModel getModelConfig(String modelName) {
        ChatModel model = null;
        
        // 1. 根据指定模型名称查询
        if (StringUtils.isNotEmpty(modelName)) {
            model = chatModelMapper.selectByModelName(modelName);
        }
        
        // 2. 如果没有找到，使用默认模型
        if (model == null) {
            model = chatModelMapper.selectDefaultModel();
        }
        
        // 3. 如果仍然没有找到，使用系统配置
        if (model == null) {
            model = new ChatModel();
            model.setModelName("gpt-4");
            model.setApiHost(configService.selectConfigByKey("sys.audit.model.url"));
            model.setApiKey(configService.selectConfigByKey("sys.audit.model.api.key"));
            model.setSystemPrompt("你是一个专业的文档审核助手，负责根据审核项要求对文档内容进行审核。");
        }
        
        return model;
    }
    

    
    /**
     * 获取相关的审核项配置
     */
    private List<DocAuditItem> getAuditItems(List<DocAuditResultDetail> details) {
        // 1. 提取审核项ID集合
        Set<Long> itemIds = new HashSet<>();
        for (DocAuditResultDetail detail : details) {
            if (detail.getAuditItemId() != null) {
                itemIds.add(detail.getAuditItemId());
            }
        }
        
        // 2. 批量查询审核项配置
        if (!itemIds.isEmpty()) {
            return auditItemMapper.selectByIds(itemIds);
        }
        
        return new ArrayList<>();
    }

} 